package com.kld.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.kld.common.constant.Constants;
import com.kld.common.constant.UserConstants;
import com.kld.common.core.domain.entity.SysDept;
import com.kld.common.core.domain.entity.SysDictData;
import com.kld.common.core.domain.entity.SysRole;
import com.kld.common.core.domain.entity.SysUser;
import com.kld.common.exception.ServiceException;
import com.kld.common.helper.LoginHelper;
import com.kld.common.utils.StringUtils;
import com.kld.common.utils.TreeBuildUtils;
import com.kld.common.utils.redis.RedisUtils;
import com.kld.common.utils.spring.SpringUtils;
import com.kld.system.mapper.SysDeptMapper;
import com.kld.system.mapper.SysRoleMapper;
import com.kld.system.mapper.SysUserMapper;
import com.kld.system.service.ISysDeptService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门管理 服务实现
 *
 * @author caonan
 */
@RequiredArgsConstructor
@Service
public class SysDeptServiceImpl implements ISysDeptService {

    private final SysDeptMapper baseMapper;
    private final SysRoleMapper roleMapper;
    private final SysUserMapper userMapper;

    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    public List<SysDept> selectDeptList(SysDept dept) {
        List<SysDept> depts = null;
//        //主键和父节点，状态，名称都为空时，认为没有传递有效参数，默认查找跟节点，并从缓存中取出
//        if(dept==null || (dept.getDeptId() == null && dept.getParentId()==null && dept.getDeptName() == null && dept.getStatus() == null)){
//            depts =  RedisUtils.getCacheObject(Constants.SYS_DEPT_LIST_KEY);
//        }else{
            depts = baseMapper.selectDeptList(dept);
//        }
        return depts;
    }



    @Override
    public List<SysDept> selectDeptListForOrg(SysDept dept) {
//        //找到单位下的虚拟部门,只允许有一个
//        List<SysDept> virtualDept =  baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
//            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
//            .apply("parent_id = {0}", dept.getParentId())
//            .apply("is_virtual_dept = 1")
//            .apply("org_type = {0}",dept.getOrgType()));
//        if(virtualDept.isEmpty()){
//            //如果单位下没有虚拟部门，则直接找本单位下的所有部门，只找一级
//            virtualDept = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
//                .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
//                .apply("parent_org_id = {0}", dept.getParentId())
//                .apply("find_in_set({0}, ancestors)", dept.getParentId())
//                .apply("org_type = {0}",dept.getOrgType()));
//
//        }else{
//            //如果单位下有虚拟部门，则找虚拟部门下的所有部门层级。
//            virtualDept.addAll(baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
//                .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
//                .apply("find_in_set({0}, ancestors)", virtualDept.get(0).getDeptId())
//                .apply("org_type = {0}",dept.getOrgType())));
//
//        }

        List<SysDept> virtualDept =baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
            .apply("parent_org_id = {0}", dept.getParentId())
            .apply("find_in_set({0}, ancestors)", dept.getParentId())
            .apply("org_type = {0}",dept.getOrgType()));
        return virtualDept;
    }

    @Override
    public long selectParentOrgById(Long deptId) {
        Long result = deptId;
        SysDept dept = baseMapper.selectById(deptId);
        if(Constants.SYS_DEPT_TYPE_DEPT.equals(dept.getOrgType())){
            result = selectParentOrgById(dept.getParentId());
        }
        return result;
    }


    @Override
    public List<SysDept> selectDeptListNoDataPermission(SysDept dept) {
        return baseMapper.selectDeptListNoDataPermission(dept);
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param sysDept 部门列表
     * @return 下拉树结构列表
     */
    @Override
    public List<Tree<Long>> buildDeptTreeSelect(SysDept sysDept) {
        List<Tree<Long>> deptTree = RedisUtils.getCacheObject(Constants.SYS_DEPT_TREE_KEY);
        List<Tree<Long>> result = new ArrayList<Tree<Long>>();
        if(deptTree == null){
            List<SysDept> depts = selectDeptList(sysDept);
            if (CollUtil.isEmpty(depts)) {
                return CollUtil.newArrayList();
            }
            result = TreeBuildUtils.build(depts, (dept, tree) ->
                tree.setId(dept.getDeptId())
                    .setParentId(dept.getParentId())
                    .setName(dept.getDeptName())
                    .setWeight(dept.getOrderNum())
                    .putExtra("deptFallName",dept.getDeptFallName()));
            resetSysDeptTree();
        }else{
            if(sysDept.getDeptId()!= null){
                for (Tree<Long> deptNode: deptTree){
                    Tree<Long> deptT = deptNode.getNode(sysDept.getDeptId());
                    if(deptT != null){
                        result.add(deptT);
                    }
                }
            }else{
                result = deptTree;
            }

        }
        return result;
    }

    /**
     * 根据角色ID查询部门树信息
     *
     * @param roleId 角色ID
     * @return 选中部门列表
     */
    @Override
    public List<Long> selectDeptListByRoleId(Long roleId) {
        SysRole role = roleMapper.selectById(roleId);
        return baseMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
    }

    /**
     * 根据部门ID查询信息
     *
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Override
    public SysDept selectDeptById(Long deptId) {
        return baseMapper.selectById(deptId);
    }

    /**
     * 根据ID查询所有子部门数（正常状态）
     *
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public long selectNormalChildrenDeptById(Long deptId) {
        return baseMapper.selectCount(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getStatus, UserConstants.DEPT_NORMAL)
            .apply("find_in_set({0}, ancestors)", deptId));
    }

    /**
     * 是否存在子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public boolean hasChildByDeptId(Long deptId) {
        return baseMapper.exists(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getParentId, deptId));
    }

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkDeptExistUser(Long deptId) {
        return userMapper.exists(new LambdaQueryWrapper<SysUser>()
            .eq(SysUser::getDeptId, deptId));
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public String checkDeptNameUnique(SysDept dept) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDept>()
            .eq(SysDept::getDeptName, dept.getDeptName())
            .eq(SysDept::getParentId, dept.getParentId())
            .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId()));
        if (exist) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验部门是否有数据权限
     *
     * @param deptId 部门id
     */
    @Override
    public void checkDeptDataScope(Long deptId) {
        if (!LoginHelper.isAdmin()) {
            SysDept dept = new SysDept();
            dept.setDeptId(deptId);
            List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
            if (CollUtil.isEmpty(depts)) {
                throw new ServiceException("没有权限访问部门数据！");
            }
        }
    }

    /**
     * 新增保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertDept(SysDept dept) {
        SysDept info = baseMapper.selectById(dept.getParentId());
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) {
            throw new ServiceException("部门停用，不允许新增");
        }
        dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
        return baseMapper.insert(dept);
    }

    /**
     * 修改保存部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int updateDept(SysDept dept) {
        SysDept newParentDept = baseMapper.selectById(dept.getParentId());
        SysDept oldDept = baseMapper.selectById(dept.getDeptId());
        if (ObjectUtil.isNotNull(newParentDept) && ObjectUtil.isNotNull(oldDept)) {
            String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
            String oldAncestors = oldDept.getAncestors();
            dept.setAncestors(newAncestors);
            updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
        }
        int result = baseMapper.updateById(dept);
        if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
            && !StringUtils.equals(UserConstants.DEPT_NORMAL, dept.getAncestors())) {
            // 如果该部门是启用状态，则启用该部门的所有上级部门
            updateParentDeptStatusNormal(dept);
        }
        //如果更新成功,刷新一下组织机构树的缓存。
        if(result>0){
            resetSysDeptTree();
        }
        return result;
    }


    /**
     * 级联修改保存组织机构类型信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int updateOrgType(SysDept dept) {
        dept.setParentOrgId(selectParentOrgById(dept.getParentId()));
        int result = baseMapper.updateById(dept);
        List<SysDept> children = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
            .apply("find_in_set({0},ancestors)", dept.getDeptId()));
        if(children != null && children.size()>0){
            for (SysDept child : children) {
                child.setOrgType(dept.getOrgType());
                if(Constants.SYS_DEPT_TYPE_ORG.equals(dept.getOrgType())){
                    child.setParentOrgId(child.getParentId());
                }else{
                    child.setParentOrgId(dept.getParentOrgId());
                }
            }
            result += baseMapper.updateDeptChildrenOrgType(children);
        }

        return result;
    }

    /**
     * 修改该部门的父级部门状态
     *
     * @param dept 当前部门
     */
    private void updateParentDeptStatusNormal(SysDept dept) {
        String ancestors = dept.getAncestors();
        Long[] deptIds = Convert.toLongArray(ancestors);
        baseMapper.update(null, new LambdaUpdateWrapper<SysDept>()
            .set(SysDept::getStatus, UserConstants.DEPT_NORMAL)
            .in(SysDept::getDeptId, Arrays.asList(deptIds)));
    }

    /**
     * 修改子元素关系
     *
     * @param deptId       被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) {
        List<SysDept> children = baseMapper.selectList(new LambdaQueryWrapper<SysDept>()
            .apply("find_in_set({0},ancestors)", deptId));
        for (SysDept child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            baseMapper.updateDeptChildren(children);
        }
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int deleteDeptById(Long deptId) {
        return baseMapper.deleteById(deptId);
    }


    @Override
    public int insertOrUpdateDeptNotCheck(SysDept dept) {
        SysDept newDept = baseMapper.selectById(dept.getDeptId());
        int result = 0;
        if(newDept==null){
            result =  baseMapper.insert(dept);
        }else{
            result =  baseMapper.updateById(dept);
        }
        return result;
    }



    /**
     * 加载单位树缓存数据
     */
    @Override
    public void loadingSysDeptTree() {
        List<SysDept> depts = selectDeptListNoDataPermission(new SysDept());
//        RedisUtils.setCacheObject(Constants.SYS_DEPT_LIST_KEY+"root",depts,false);
//        Map<Long, List<SysDept>> sysDataMap = depts.stream().collect(Collectors.groupingBy(SysDept::getParentId));
//        sysDataMap.forEach((k,v) -> {
//            String deptKey = getCacheKey(k);
//            List<SysDept> deptList = v.stream()
//                .sorted(Comparator.comparing(SysDept::getOrderNum))
//                .collect(Collectors.toList());
//            RedisUtils.setCacheObject(deptKey, deptList);
//        });

        List<Tree<Long>> deptTree = TreeBuildUtils.build(depts, (dept, tree) ->
            tree.setId(dept.getDeptId())
                .setParentId(dept.getParentId())
                .setName(dept.getDeptName())
                .setWeight(dept.getOrderNum())
                .putExtra("deptFallName",dept.getDeptFallName())
        );
        RedisUtils.setCacheObject(Constants.SYS_DEPT_TREE_KEY,deptTree,false);
    }

    /**
     * 清空单位树缓存数据
     */
    @Override
    public void clearSysDeptTree() {
        Collection<String> keys = RedisUtils.keys(Constants.SYS_DEPT_TREE_KEY + "*");
        RedisUtils.deleteObject(keys);

//        keys = RedisUtils.keys(Constants.SYS_DEPT_LIST_KEY + "*");
//        RedisUtils.deleteObject(keys);
    }

    /**
     * 重置单位树缓存数据
     */
    @Override
    public void resetSysDeptTree() {
        clearSysDeptTree();
        loadingSysDeptTree();
    }

    @Override
    public SysDept selectOrgById(Long deptId) {
        SysDept dept = baseMapper.selectById(deptId);
        if(Constants.SYS_DEPT_TYPE_DEPT.equals(dept.getOrgType())){
            return selectOrgById(dept.getParentId());
        }else{
            return dept;
        }
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    String getCacheKey(Long configKey) {
        return Constants.SYS_DEPT_LIST_KEY + configKey;
    }
}
